Source

womacs / develop_src / EmacsLikeCommands.bas

Full commit
   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  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
 172
 173
 174
 175
 176
 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
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
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
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
Attribute VB_Name = "EmacsLikeCommands"
' womacs

Option Explicit


Public is_desc_key As Boolean
Public statusbar_prefix As String

Public search_fwd As Boolean

' doc local
Public womacs_on As Boolean
Public mark_set As Boolean     ' has mark been set?
Public mark_pos As Long        ' position of the mark




Public num_arg As Integer  ' numeric argument
Public self_ins_text As String
'    While num_arg < 0
'        do_a()
'
'        num_arg = num_arg + 1
'    Wend
'
'    While num_arg > 0
'        do_b()
'
'        num_arg = num_arg - 1
'    Wend
'    num_arg = 1  ' reset num_arg to 1

Dim action_record_balance As Integer    ' for debug

'Public kill_whole_line As Boolean
Public delete_word As Boolean


Sub store_doc_locals(ByVal Doc As Document)
    push_saved_state Doc
    
    Doc.Variables("womacs_on") = CStr(womacs_on)
    Doc.Variables("mark_set") = CStr(mark_set)
    Doc.Variables("mark_pos") = CStr(mark_pos)
    
    pop_saved_state Doc
End Sub


Sub load_doc_locals(ByVal Doc As Document)
    womacs_on = False
    mark_set = False
    mark_pos = -1

    On Error Resume Next
    womacs_on = CBool(Doc.Variables("womacs_on"))
    mark_set = CBool(Doc.Variables("mark_set"))
    mark_pos = CLng(Doc.Variables("mark_pos"))
End Sub


Sub delete_all_womacs_vars(ByVal Doc As Document)
    push_saved_state Doc
    
    On Error Resume Next

    Doc.Variables("womacs_on").Delete
    Doc.Variables("mark_set").Delete
    Doc.Variables("mark_pos").Delete
    
    pop_saved_state Doc

End Sub


Sub begin_action(name As String)
    ' need word 2010
    If StrComp(Application.version, "14.0") = -1 Then
        Exit Sub
    End If
    
    Debug.Assert action_record_balance = 0
    action_record_balance = action_record_balance + 1
    Application.UndoRecord.StartCustomRecord "Undo " & name
End Sub


Sub end_action()
    ' need word 2010
    If StrComp(Application.version, "14.0") = -1 Then
        Exit Sub
    End If
    
    Debug.Assert action_record_balance = 1
    action_record_balance = action_record_balance - 1
    Application.UndoRecord.EndCustomRecord
End Sub


Sub doc_of_set_mark_command()
    doc_string = "Set the mark where point is."
End Sub
Sub set_mark_command()
'C-SPC

    Dim old_mark_pos As Long

    If mark_set Then
        select_nothing
        ' if point has not been moved since mark is set, then cancel the mark
        If mark_pos = Selection.Start Then
            mark_set = False
            Application.StatusBar = "Mark deactivated"
            Exit Sub
        End If
    End If

    old_mark_pos = mark_pos

    mark_set = True
    mark_pos = Selection.Start
    'Debug.Print mark_pos

    If mark_pos = old_mark_pos Then
        Application.StatusBar = "Mark activated"
    Else
        Application.StatusBar = "Mark set"
    End If


    complete
End Sub


Sub select_nothing()
    ' if there is no highlight
    If Selection.type = wdSelectionIP Then
        Exit Sub
    End If

    ' move cursor to make highlight disapper
'    If mark_pos <= Selection.Start Then
'        Selection.Collapse Direction:=wdCollapseEnd
'    Else
'        Selection.Collapse Direction:=wdCollapseStart
'    End If
    
    If Selection.StartIsActive Then
        Selection.Collapse direction:=wdCollapseStart
    Else
        Selection.Collapse direction:=wdCollapseEnd
    End If
    

End Sub


Sub doc_of_keyboard_quit()
    doc_string = "Signal a `quit' condiction."
End Sub
Sub keyboard_quit()
'C-g
    Application.StatusBar = "Quit"

    mark_set = False
    select_nothing
    
    complete
    
    'restore to the global_keymap
    Set current_keymap = global_keymap
    global_keymap.bind ActiveDocument
    
    'restore the IME status
    ImeRestoreStatus

End Sub


Sub doc_of_kill_line()
    doc_string = "Move point right one character."
End Sub
Sub kill_line()
'C-k

    mark_set = False
    select_nothing
    
    ' move to the end of line
    Selection.EndKey Unit:=wdLine, Extend:=wdExtend

    If Selection.type <> wdSelectionIP _
            And Asc(Selection.Characters.Last.Text) = 13 _
            And Asc(Selection.Characters.First.Text) <> 13 Then
        Selection.MoveLeft Unit:=wdCharacter, Count:=1, Extend:=wdExtend
    End If
    

    'Selection.StartIsActive = Not Selection.StartIsActive
    
    If Selection.type <> wdSelectionIP Then
        Selection.Cut
    End If


    complete
End Sub


Sub doc_of_kill_region()
    doc_string = "Kill (""cut"") text between point and mark."
End Sub
Sub kill_region()
'C-w
    On Error Resume Next
    'Selection.Cut
    Application.Run macroname:="EditCut"
    
    mark_set = False

    complete
End Sub


Sub doc_of_delete_region()
    doc_string = "Delete the text between point and mark."
End Sub
Sub delete_region()
'C-c w
    On Error Resume Next
    Selection.Delete Unit:=wdCharacter, Count:=1
    
    mark_set = False

    complete
End Sub


'    While num_arg < 0
'        do_a()
'
'        num_arg = num_arg + 1
'    Wend
'
'    While num_arg > 0
'        do_b()
'
'        num_arg = num_arg - 1
'    Wend
Sub doc_of_kill_word()
    doc_string = "Kill a word forward, skipping over intervening delimiters."
End Sub
Sub kill_word()
'M-d
    On Error Resume Next

    mark_set = False
    select_nothing
    
    begin_action "kill word"
    
    If delete_word Then
        While num_arg > 0
            Application.Run macroname:="DeleteWord"
            num_arg = num_arg - 1
        Wend
    Else
        Selection.MoveRight Unit:=wdWord, Count:=num_arg, Extend:=wdExtend
        Selection.StartIsActive = Not Selection.StartIsActive   ' when select_nothing in undo, move point to a correct position
        Selection.Cut
    End If
    
    end_action
    
    complete
End Sub


Sub doc_of_backward_kill_word()
    doc_string = "Kill characters backward until encountering the beginning of a word."
End Sub
Sub backward_kill_word()
'M-backspace
    begin_action "backward kill word"
    
    If delete_word Then
        While num_arg > 0
            Application.Run macroname:="DeleteBackWord"
            num_arg = num_arg - 1
        Wend
    Else
        Selection.MoveLeft Unit:=wdWord, Count:=num_arg, Extend:=wdExtend
        Selection.StartIsActive = Not Selection.StartIsActive
        Selection.Cut
    End If
    
    end_action
    
    complete
    
End Sub


Sub doc_of_kill_ring_save()
    doc_string = "Copy"
End Sub
Sub kill_ring_save()
'M-w
    On Error Resume Next
    'Selection.Copy
    Application.Run macroname:="EditCopy"

    select_nothing
    mark_set = False


    complete
End Sub


Sub doc_of_yank()
    doc_string = "Paste"
End Sub
Sub yank()
'C-y
    mark_set = False
    select_nothing
    
    'Selection.PasteAndFormat (wdFormatPlainText)
    'Selection.PasteAndFormat (wdFormatOriginalFormatting)
    Application.Run macroname:="EditPaste"

    complete
End Sub


Sub doc_of_delete_char()
    doc_string = "Delete the following one character."
End Sub
Sub delete_char()
'C-d
    mark_set = False
    select_nothing
    
    Selection.Delete Unit:=wdCharacter, Count:=num_arg

    complete
End Sub


Sub doc_of_upcase_word()
    doc_string = "Convert following word to upper case, moving over."
End Sub
Sub upcase_word()
'M-u
    select_nothing
    mark_set = False

    begin_action "upcase word"
    
    If num_arg < 0 Then
        Dim point_pos As Long
        point_pos = Selection.Start
        Selection.MoveLeft Unit:=wdWord, Count:=-num_arg

        While Selection.Start < point_pos
            Selection.Range.Case = wdUpperCase
            Selection.MoveRight Unit:=wdWord, Count:=1
        Wend


    End If

    While num_arg > 0
        Selection.Range.Case = wdUpperCase
        Selection.MoveRight Unit:=wdWord, Count:=1

        num_arg = num_arg - 1
    Wend
    
    end_action

    complete
End Sub


Sub doc_of_downcase_word()
    doc_string = "Convert following word to lower case, moving over."
End Sub
Sub downcase_word()
'M-l

    select_nothing
    mark_set = False
    
    begin_action "downcase word"

    If num_arg < 0 Then
        Dim point_pos As Long
        point_pos = Selection.Start
        Selection.MoveLeft Unit:=wdWord, Count:=-num_arg

        While Selection.Start < point_pos
            Selection.Range.Case = wdLowerCase
            Selection.MoveRight Unit:=wdWord, Count:=1
        Wend


    End If

    While num_arg > 0
        Selection.Range.Case = wdLowerCase
        Selection.MoveRight Unit:=wdWord, Count:=1

        num_arg = num_arg - 1
    Wend

    end_action
    
    complete
End Sub


Sub doc_of_capitalize_word()
    doc_string = "Capitalize the following word (or ARG words), moving over."
End Sub
Sub capitalize_word()
'M-c
    select_nothing
    mark_set = False
    
    begin_action "capitalize word"

    If num_arg < 0 Then
        Dim point_pos As Long
        point_pos = Selection.Start
        Selection.MoveLeft Unit:=wdWord, Count:=-num_arg

        While Selection.Start < point_pos
            Selection.Range.Case = wdTitleWord
            Selection.MoveRight Unit:=wdWord, Count:=1
        Wend


    End If

    While num_arg > 0
        Selection.Range.Case = wdTitleWord
        Selection.MoveRight Unit:=wdWord, Count:=1

        num_arg = num_arg - 1
    Wend

    end_action
    
    complete
End Sub


Sub doc_of_newline()
    doc_string = "Insert a newline."
End Sub
Sub newline()
'C-m
    select_nothing
    mark_set = False
    
    begin_action "newline"

    While num_arg > 0
        Selection.TypeParagraph

        num_arg = num_arg - 1
    Wend

    end_action
    complete
End Sub


Sub doc_of_open_line()
    doc_string = "Insert a newline and leave point before it."
End Sub
Sub open_line()
'C-o
    select_nothing
    mark_set = False
    
    begin_action ("open line")

    Dim i As Integer
    For i = 1 To num_arg
        Selection.TypeParagraph
    Next i
    
    Selection.MoveLeft Unit:=wdCharacter, Count:=num_arg
    
    end_action

    complete

End Sub


Sub doc_of_forward_word()
    doc_string = "Move point forward one word."
End Sub
Sub forward_word()
'M-f
    If mark_set Then
        Selection.MoveRight Unit:=wdWord, Count:=num_arg, Extend:=wdExtend
    Else
        Selection.MoveRight Unit:=wdWord, Count:=num_arg, Extend:=wdMove
    End If

    complete
End Sub


Sub doc_of_backward_word()
    doc_string = "Move backward until encountering the beginning of a word."
End Sub
Sub backward_word()
'M-b
    If mark_set Then
        Selection.MoveLeft Unit:=wdWord, Count:=num_arg, Extend:=wdExtend
    Else
        Selection.MoveLeft Unit:=wdWord, Count:=num_arg, Extend:=wdMove
    End If

    complete
End Sub


Sub doc_of_forward_char()
    doc_string = "Move point right one character."
End Sub
Sub forward_char()
'C-f
    If mark_set Then
        Selection.MoveRight Unit:=wdCharacter, Count:=num_arg, Extend:=wdExtend
    Else
        Selection.MoveRight Unit:=wdCharacter, Count:=num_arg, Extend:=wdMove
    End If
    
    complete
End Sub


Sub doc_of_backward_char()
    doc_string = "Move point left one character."
End Sub
Sub backward_char()
'C-b
    If mark_set Then
        Selection.MoveLeft Unit:=wdCharacter, Count:=num_arg, Extend:=wdExtend
    Else
        Selection.MoveLeft Unit:=wdCharacter, Count:=num_arg, Extend:=wdMove
    End If

    complete
End Sub


Sub doc_of_previous_line()
    doc_string = "Move cursor vertically up one line."
End Sub
Sub previous_line()
'C-p
    If mark_set Then
        Selection.MoveUp Unit:=wdLine, Count:=num_arg, Extend:=wdExtend
    Else
        Selection.MoveUp Unit:=wdLine, Count:=num_arg, Extend:=wdMove
    End If

    complete
End Sub


Sub doc_of_next_line()
    doc_string = "Move cursor vertically down one line."
End Sub
Sub next_line()
'C-n
    If mark_set Then
        Selection.MoveDown Unit:=wdLine, Count:=num_arg, Extend:=wdExtend
    Else
        Selection.MoveDown Unit:=wdLine, Count:=num_arg, Extend:=wdMove
    End If

    complete
End Sub


' yet not support C-u
Sub doc_of_move_beginning_of_line()
    doc_string = "Move point to beginning of current line."
End Sub
Sub move_beginning_of_line()
'C-a
    If mark_set Then
        Selection.HomeKey Unit:=wdLine, Extend:=wdExtend
    Else
        Selection.HomeKey Unit:=wdLine, Extend:=wdMove
    End If

    complete
End Sub


' yet not support C-u
Sub doc_of_move_end_of_line()
    doc_string = "Move point to end of current line."
End Sub
Sub move_end_of_line()
'C-e
    If mark_set Then
        Selection.EndKey Unit:=wdLine, Extend:=wdExtend
    Else
        Selection.EndKey Unit:=wdLine, Extend:=wdMove
    End If

    complete
End Sub


Sub doc_of_backward_sentence()
    doc_string = "Move backward to start of sentence."
End Sub
Sub backward_sentence()
'M-a
    If mark_set Then
        Selection.MoveLeft Unit:=wdSentence, Count:=num_arg, Extend:=wdExtend
    Else
        Selection.MoveLeft Unit:=wdSentence, Count:=num_arg, Extend:=wdMove
    End If
    
    complete
End Sub


Sub doc_of_forward_sentence()
    doc_string = "Move forward to next end of sentence."
End Sub
Sub forward_sentence()
'M-e
    If mark_set Then
        Selection.MoveRight Unit:=wdSentence, Count:=num_arg, Extend:=wdExtend
    Else
        Selection.MoveRight Unit:=wdSentence, Count:=num_arg, Extend:=wdMove
    End If

    complete
End Sub


Sub doc_of_beginning_of_buffer()
    doc_string = "Move point to the beginning of the buffer."
End Sub
Sub beginning_of_buffer()
'C-home
    If mark_set Then
        Selection.HomeKey Unit:=wdStory, Extend:=wdExtend
    Else
        Selection.HomeKey Unit:=wdStory
    End If
    
    complete
End Sub


Sub doc_of_end_of_buffer()
    doc_string = "Move point to the end of the buffer."
End Sub
Sub end_of_buffer()
'C-end
    If mark_set Then
        Selection.EndKey Unit:=wdStory, Extend:=wdExtend
    Else
        Selection.EndKey Unit:=wdStory
    End If
    
    complete
End Sub


Sub doc_of_forward_page()
    doc_string = "Move forward to page boundary."
End Sub
Sub forward_page()
'C-x ]
    Selection.GoToNext What:=wdGoToPage
    
    complete
End Sub


Sub doc_of_backward_page()
    doc_string = "Move backward to page boundary."
End Sub
Sub backward_page()
'C-x [
    Selection.GoToPrevious What:=wdGoToPage
    
    complete
End Sub


Sub doc_of_forward_paragraph()
    doc_string = "Move forward to end of paragraph."
End Sub
Sub forward_paragraph()
'M-}
    If mark_set Then
        Selection.MoveDown Unit:=wdParagraph, Count:=num_arg, Extend:=wdExtend
    Else
        Selection.MoveDown Unit:=wdParagraph, Count:=num_arg, Extend:=wdMove
    End If

    complete
End Sub


Sub doc_of_backward_paragraph()
    doc_string = "Move backward to start of paragraph."
End Sub
Sub backward_paragraph()
'M-{
    If mark_set Then
        Selection.MoveUp Unit:=wdParagraph, Count:=num_arg, Extend:=wdExtend
    Else
        Selection.MoveUp Unit:=wdParagraph, Count:=num_arg, Extend:=wdMove
    End If

    complete
End Sub


Sub doc_of_scroll_up_command()
    doc_string = "Scroll text of selected window upward ARG lines; or near full screen if no ARG."
End Sub
Sub scroll_up_command()
'C-v
    If mark_set Then
        Selection.MoveDown Unit:=wdScreen, Count:=num_arg, Extend:=wdExtend
    Else
        Selection.MoveDown Unit:=wdScreen, Count:=num_arg, Extend:=wdMove
    End If

    complete
End Sub


Sub doc_of_scroll_down_command()
    doc_string = "Scroll text of selected window down ARG lines; or near full screen if no ARG."
End Sub
Sub scroll_down_command()
'M-v
    If mark_set Then
        Selection.MoveUp Unit:=wdScreen, Count:=num_arg, Extend:=wdExtend
    Else
        Selection.MoveUp Unit:=wdScreen, Count:=num_arg, Extend:=wdMove
    End If

    complete
End Sub


' after LTrim
' "NUM str"
' "str"
' "NUM "
' "NUM"
' ""
Sub doc_of_universal_argument()
    doc_string = "Begin a numeric argument for the following command."
End Sub
Sub universal_argument()
'C-u
    frmUniArg.Show
    ' deal with self insert command
    If self_ins_text <> "" Then
        While num_arg > 0
            Selection.TypeText Text:=self_ins_text

            num_arg = num_arg - 1
        Wend
        num_arg = 1
    End If
End Sub


Sub doc_of_execute_extended_command()
    doc_string = "Read function name, then read its arguments and call it."
End Sub
Sub execute_extended_command()
'M-x
    Dim cmd As String
    Dim arg As String
    cmd = InputBox("enter command name", "M-x")
    
    cmd = Replace(cmd, "-", "_")

    ' call read_args_for_XXX to prepare arg

    'Application.Run(cmd, arg)
    On Error Resume Next
    Application.Run cmd
End Sub


Sub doc_of_transpose_chars()
    doc_string = "Interchange characters around point, moving forward one character."
End Sub
Sub transpose_chars()
'C-t

    begin_action "transpose chars"

    Dim c
    Selection.MoveLeft Unit:=wdCharacter, Count:=1, Extend:=wdExtend
    c = Selection
    Selection.Delete
    Selection.Collapse direction:=wdCollapseEnd
    Selection.MoveRight Unit:=wdCharacter, Count:=num_arg
    Selection.InsertAfter c
    Selection.Collapse
    
    end_action

    complete
End Sub


Sub doc_of_transpose_words()
    doc_string = "Interchange words around point, leaving point at end of them."
End Sub
Sub transpose_words()
'M-t

    begin_action "transpose words"

    Dim w
    Selection.MoveLeft Unit:=wdWord, Count:=1, Extend:=wdExtend
    w = Selection
    Selection.Delete
    Selection.Collapse direction:=wdCollapseEnd
    Selection.MoveRight Unit:=wdWord, Count:=num_arg
    Selection.InsertAfter w
    Selection.Collapse
    
    end_action
    
    complete
End Sub


Sub doc_of_exchange_point_and_mark()
    doc_string = "Put the mark where point is now, and point where the mark is now."
End Sub
Sub exchange_point_and_mark()
'C-x C-x
    
    ' if region is not highlight, highlight it first.
    If Selection.type = wdSelectionIP Then
        Dim point_pos As Long
        point_pos = Selection.Start
        
        If mark_pos <= point_pos Then
            Selection.Start = mark_pos
            Selection.StartIsActive = False
        Else
            Selection.End = mark_pos
            Selection.StartIsActive = True
            
        End If
        
        mark_set = True
    End If
    
    
    Selection.StartIsActive = Not Selection.StartIsActive
    
    If Selection.StartIsActive Then
        mark_pos = Selection.End
    Else
        mark_pos = Selection.Start
    End If

    complete
End Sub


Sub doc_of_downcase_region()
    doc_string = "Convert the region to lower case."
End Sub
Sub downcase_region()
'C-x C-l
    Selection.Range.Case = wdLowerCase
    
    select_nothing
    mark_set = False

    complete
End Sub


Sub doc_of_upcase_region()
    doc_string = "Convert the region to upper case."
End Sub
Sub upcase_region()
'C-x C-u
    Selection.Range.Case = wdUpperCase

    select_nothing
    mark_set = False
    
    complete
End Sub


Sub doc_of_mark_whole_buffer()
    doc_string = "Put point at beginning and mark at end of buffer."
End Sub
Sub mark_whole_buffer()
'C-x h
    ' Selection.WholeStory
    Selection.EndKey Unit:=wdStory
    mark_set = True
    mark_pos = Selection.Start
    
    Selection.HomeKey Unit:=wdStory, Extend:=wdExtend

    complete
End Sub


Sub doc_of_save_buffer()
    doc_string = "Save current buffer in visited file if modified."
End Sub
Sub save_buffer()
'C-x C-s

    On Error Resume Next
    ActiveDocument.Save

    complete
End Sub


Sub doc_of_recenter()
    doc_string = "Move current buffer line to the specified window line."
End Sub
Sub recenter()
'C-l

    Application.ScreenUpdating = False
    
    ActiveWindow.ActivePane.VerticalPercentScrolled = 0
    ActiveWindow.ScrollIntoView Selection.Range, True
    
    Application.ScreenUpdating = True
    
    complete
End Sub


Sub doc_of_undo()
    doc_string = "Undo some previous changes."
End Sub
Sub undo()
'C-z
    On Error Resume Next
    Application.Run "EditUndo"
    select_nothing
    complete
End Sub


Function other_pane_index(this_pane_index As Integer)
    Debug.Assert this_pane_index = 1 Or this_pane_index = 2
    If this_pane_index = 1 Then
        other_pane_index = 2
    Else
        other_pane_index = 1
    End If
    
End Function


Sub doc_of_split_window_vertically()
    doc_string = "Split the document window."
End Sub
Sub split_window_vertically()
'C-x 2

    Application.ScreenUpdating = False
    
    ' macro DocSplit is interactive
    'Application.Run MacroName:="DocSplit"
    
    ActiveDocument.ActiveWindow.Split = True
    
    ActiveWindow.Panes(1).Activate
    ActiveWindow.ScrollIntoView Selection.Range, True
    
    
    Debug.Print Selection.Start, Selection.End
    Dim sel_start As Long
    Dim sel_end As Long
    sel_start = Selection.Start
    sel_end = Selection.End
    

    ActiveWindow.Panes(other_pane_index(ActiveWindow.ActivePane.index)).Activate
    Selection.Start = sel_start
    Selection.End = sel_end
    ActiveWindow.ScrollIntoView Selection.Range, True
    
    
    ActiveWindow.Panes(1).Activate
    'ActiveWindow.ScrollIntoView Selection.Range, True
    
    Application.ScreenUpdating = True
    

    complete
End Sub


Sub doc_of_other_window()
    doc_string = "Activate another pane."
End Sub
Sub other_window()
'C-x o
    If ActiveWindow.Panes.Count > 1 Then
        ActiveWindow.Panes(other_pane_index(ActiveWindow.ActivePane.index)).Activate
    End If
    
    complete
End Sub


Sub doc_of_delete_window()
    doc_string = "Close current pane."
End Sub
Sub delete_window()
'C-x 0
    If ActiveWindow.Panes.Count > 1 Then
        ActiveWindow.ActivePane.Close
    End If
    
    complete
End Sub


Sub doc_of_delete_other_windows()
    doc_string = "Remove the document window split."
End Sub
Sub delete_other_windows()
'C-x 1
    'Application.Run MacroName:="ClosePane"
    
'   if we use Split = Flase, we have no idea about which pane will remains.
'    ActiveDocument.ActiveWindow.Split = False

    While ActiveWindow.Panes.Count > 1
        ActiveWindow.ActivePane.Next.Activate
        ActiveWindow.ActivePane.Close
    Wend
    

    complete
End Sub


Sub doc_of_set_justification_left()
    doc_string = "Align text to the left."
End Sub
Sub set_justification_left()
'M-j l
    Selection.ParagraphFormat.Alignment = wdAlignParagraphLeft
    complete
End Sub


Sub doc_of_set_justification_center()
    doc_string = "Center text."
End Sub
Sub set_justification_center()
'M-j c
    Selection.ParagraphFormat.Alignment = wdAlignParagraphCenter
    complete
End Sub


Sub doc_of_set_justification_right()
    doc_string = "Align text to the right."
End Sub
Sub set_justification_right()
'M-j r
    Selection.ParagraphFormat.Alignment = wdAlignParagraphRight
    complete
End Sub


Sub doc_of_set_justification_full()
    doc_string = "Justify."
End Sub
Sub set_justification_full()
'M-j b
    Selection.ParagraphFormat.Alignment = wdAlignParagraphJustify
    complete
End Sub


Sub doc_of_describe_key()
    doc_string = "Display documentation of the function invoked by KEY."
End Sub
Sub describe_key()
'C-h k
    is_desc_key = True
    statusbar_prefix = "Describe key: "
    StatusBar = statusbar_prefix
    complete
End Sub


Sub doc_of_describe_function()
    doc_string = "Display the documentation of FUNCTION (a symbol)."
End Sub
Sub describe_function()
'C-h f

    Dim cmd As String
    cmd = InputBox("enter function name", "Describe function")
    
    cmd = Replace(cmd, "-", "_")

    Dim doc_string_proc_name As String
    doc_string_proc_name = "doc_of_" & cmd
    
    On Error Resume Next ' there may NOT be a corresponding doc string porc
    Application.Run macroname:=doc_string_proc_name
    
    'display information about this command
    MsgBox doc_string, Title:=cmd
    
    reset_doc_string

    complete
End Sub


Sub doc_of_isearch_forward()
    doc_string = "Do incremental search forward."
End Sub
Sub isearch_forward()
'C-s
    search_fwd = True
    frmISearch.cbWildcards = False
    frmISearch.Show 'vbModeless
End Sub


Sub doc_of_isearch_backward()
    doc_string = "Do incremental search backward."
End Sub
Sub isearch_backward()
'C-r
    search_fwd = False
    frmISearch.cbWildcards = False
    frmISearch.Show vbModeless
End Sub


Sub doc_of_isearch_forward_regexp()
    doc_string = "Do incremental search forward for regular expression."
End Sub
Sub isearch_forward_regexp()
'C-M-s
    search_fwd = True
    frmISearch.cbWildcards = True
    frmISearch.Show vbModeless
End Sub


Sub doc_of_isearch_backward_regexp()
    doc_string = "Do incremental search backward for regular expression."
End Sub
Sub isearch_backward_regexp()
'C-M-r
    search_fwd = False
    frmISearch.cbWildcards = True
    frmISearch.Show vbModeless
End Sub


Sub doc_of_delete_horizontal_space()
    doc_string = "Delete all spaces and tabs around point."
End Sub
Sub delete_horizontal_space()
'M-\
    Application.ScreenUpdating = False
    
    Selection.MoveStartWhile cset:=" ", Count:=wdBackward
    Selection.MoveEndWhile cset:=" ", Count:=wdForward
    If Selection.type = wdSelectionNormal Then
        Selection.Delete
    End If
    
    Application.ScreenUpdating = True
End Sub


Sub doc_of_just_one_space()
    doc_string = "Delete all spaces and tabs around point, leaving one space (or N spaces)."
End Sub
Sub just_one_space()
'M-SPC
    Application.ScreenUpdating = False
    
    Selection.MoveStartWhile cset:=" ", Count:=wdBackward
    Selection.MoveEndWhile cset:=" ", Count:=wdForward
    If Selection.type = wdSelectionNormal Then
        Selection.Delete
    End If
    
    Selection.TypeText " "
    
    Application.ScreenUpdating = True
End Sub


Sub complete()
    num_arg = 1
End Sub


Sub prompt_undefined()
    StatusBar = "key undefined"
    
    complete
End Sub